#include "main.h"
FILE * compres (FILE * fileToRead,fileHead * fileHd)
{
	unsigned char * buf_in = (unsigned char*) calloc (SIZE_BUF,sizeof(char));
	unsigned char * buf_out = (unsigned char *) calloc (SIZE_BUF,sizeof(char));
	unsigned char * hufTreeInStr = NULL;
	size_t un_bits = 0;
	size_t len = 0;
	FILE * fileToWrite = NULL;
	char * temp_name = NULL;
	char X[] = "XXXXXX";
	int rc = 0;
	int i = 0;
	int rc2 = 0;
	unsigned long long int count = 0;
	int n = 1;	
	int count_2 = 0;
	unsigned int qwe = 0;
	__HufTree * head = NULL;
	struct stat * fileStat = (struct stat*)calloc (1,sizeof(struct stat));
	unsigned char **tables = NULL;
	str_inf * inf = (str_inf *)calloc (1,sizeof(str_inf));
	envInf.inf = inf;
	if (!inf) cl_exit (COMPRESS,MEMORY_ERR);
	if (!buf_in) cl_exit (COMPRESS,MEMORY_ERR);
	if (!buf_out) cl_exit (COMPRESS,MEMORY_ERR);
	envInf.buf = (char*) buf_in;	
	envInf.buf_2 = buf_out;
	head = mkH_TInit (fileToRead);
#ifdef __DEBUG_
	print (head,NULL,0);
	system ("pause");
#endif
	fseek (fileToRead,0,SEEK_SET);	
	tables = (unsigned char**) calloc (256,sizeof(char*));
	envInf.tables = tables;
	for (i = 0; i<256; i++)	{
		tables[i] = makeTables (i,0,head,NULL);
		if (tables[i])
			count_2 ++;
	}
	if (count_2 != 1)	{
	hufTreeInStr = HufTreeToStr (head,&len);
	fileHd->huff_block = len;
	envInf.hufTreeinStr = hufTreeInStr;
	temp_name = (char*) realloc (fileHd->fileName,(fileHd->sizeName + 7)*sizeof(char));
	temp_name[fileHd->sizeName] = 0;
	i = 0;
	envInf.tmpFileName = temp_name;
	if (!temp_name) cl_exit (COMPRESS,MEMORY_ERR);
	strcat (temp_name,X);	
	temp_name = mktemp (temp_name);
	fileToWrite = fopen (temp_name,"wb+");
	envInf.fileToWrite = fileToWrite;
	if (!fileToWrite)	cl_exit (COMPRESS,OPEN_FILE_ERR);
	if ((rc = fwrite (hufTreeInStr,sizeof(char),len,fileToWrite)) != len) cl_exit (COMPRESS,WRITE_ERR);
	count += rc;
	rc2 = 0;
	while (n == 1)
	{
		if (rc2 != NEW_BUF_OUT)	{
			rc = fread (buf_in,sizeof(char),SIZE_BUF,fileToRead);
			inf->max_pos = rc; inf->ind_char = 0;
			inf->ind_bits = 0;
		}
		if (rc == SIZE_BUF)	{	
			rc2 = CharInBits (buf_in,buf_out,tables,inf);
			if (rc2 != NEW_BUF_IN)	{
				rc = fwrite (buf_out,sizeof(char),SIZE_BUF,fileToWrite);
				if (rc != SIZE_BUF)	cl_exit (COMPRESS,WRITE_ERR);
				count += rc;
				memset (buf_out,0,sizeof(char)*SIZE_BUF);
				inf->cur_pos = 1;
			}	
		}
		else if (rc > 0)	{	
			rc2 = CharInBits (buf_in,buf_out,tables,inf);
			if (rc2 != NEW_BUF_OUT)	{
				if ((inf->u_bits == 8) && (rc2 == NEW_BUF_IN))	inf->cur_pos--;
				rc = fwrite (buf_out,sizeof(char),inf->cur_pos,fileToWrite);
				if (rc != (inf->cur_pos)) cl_exit(COMPRESS,WRITE_ERR);
				count += rc;
				n = 0;	free (buf_in);	
				envInf.buf = NULL;
				free (buf_out);
				envInf.buf_2 = NULL;
			}
		else {
			rc = fwrite (buf_out,sizeof(char),SIZE_BUF,fileToWrite);
			if (rc != SIZE_BUF) cl_exit (COMPRESS,WRITE_ERR);
			count += rc;
			memset (buf_out,0,SIZE_BUF);
			inf->cur_pos = 1;
			rc = 32;
		}
		} else {
			if ((inf->u_bits != 8) && (inf->u_bits != 0) || (inf->cur_pos > 1))	{
				rc = fwrite (buf_out,sizeof(char),inf->cur_pos,fileToWrite);
				if (rc !=( inf->cur_pos)) cl_exit (COMPRESS,WRITE_ERR);
				count += rc;
				n = 0;
				free (buf_in);
				envInf.buf = NULL;
				free (buf_out);
				envInf.buf_2 = NULL;
			}
			else break;
		}
	}
	if (inf->u_bits < 8)	fileHd->huff_ubits |= inf->u_bits; else {}
	///
	} else {
		fileHd->huff_ubits |= _1_CHAR;
		temp_name = (char*) realloc (fileHd->fileName,(fileHd->sizeName + 7)*sizeof(char));
		temp_name[fileHd->sizeName] = 0;
		i = 0;
		envInf.tmpFileName = temp_name;
		if (!temp_name) cl_exit (COMPRESS,MEMORY_ERR);
		strcat (temp_name,X);	
		temp_name = mktemp (temp_name);
		fileToWrite = fopen (temp_name,"wb+");
		envInf.fileToWrite = fileToWrite;
		if (!fileToWrite)	cl_exit (COMPRESS,OPEN_FILE_ERR);
		rc = fread (buf_in,sizeof(char),1,fileToRead);
		if (rc != 1) cl_exit (COMPRESS,READ_ERR);
		rc = fwrite (buf_in,sizeof(char),1,fileToWrite);
		if (fileHd->huff_ubits & LEN_8_B)	{
			intWrite (fileToWrite,fileHd->fileSize,SIZE_T_8,NULL);
			fileHd->huff_file_len = 9;
		} else {
			intWrite (fileToWrite,fileHd->fileSize,SIZE_T_4,NULL);
			fileHd->huff_file_len = 5;
		}
	}
	free (inf);	
	envInf.inf = NULL;
	fclose (fileToRead);
	//fileToRead = fileToWrite;
	envInf.fileToRead = fileToWrite;
	envInf.fileToWrite = NULL;
	for (n = 0; n < 256; n++)	{
		if (tables[n])	free(tables[n]);
	}
	free (tables);
	envInf.tables = NULL;
	if (count_2 != 1)	{
		fileHd->huff_file_len = count;
	}
	fflush (fileToWrite); 
	return fileToWrite;
}